package io.mft.commons.db.source;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Session;
import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.setting.Setting;
import io.mft.commons.db.mapper.SQLExecutorDbMapper;
import io.mft.commons.exception.MFTException;
import io.mft.commons.function.response.kv.KVMap;

public class DbProvider {
	static Log log = LogFactory.get();
	private static DbProvider instance = new DbProvider();

	public static DbProvider getInstance() {
		return instance;
	}

	private String defaultDatasourceId;

	public void setDefaultDatasourceId(String defaultDatasourceId) {
		this.defaultDatasourceId = defaultDatasourceId;
	}

	public String getDefaultDatasourceId() {
		if (StrUtil.isEmpty(defaultDatasourceId)) {
			throw new MFTException("默认数据源ID未初始化,请检查！");
		}
		return defaultDatasourceId;
	}

	private DbProvider() {
		// initConfig();
	}

	private List<String> datasourceIdList = new ArrayList<>();

	public List<String> getDatasourceIdList() {
		return datasourceIdList;
	}

	private Map<String, DataSource> datasourceMap = new HashMap<String, DataSource>();

	private HashMap<String, String> refDatasourceIdMap = new HashMap<>();
	Setting setting = new Setting();
	DSFactory dsFactory;
	{
		try {
			dsFactory = DSFactory.create(setting);
			DSFactory.setCurrentDSFactory(dsFactory);
		} catch (Exception e) {
			log.error(e);
		}

	}


	public void addRefDatasourceId(String id,String refDatasourceId) {
		refDatasourceIdMap.put(id, refDatasourceId);
	}

	public boolean addDatasourceConfig(String datasourceId, Map<String, String> config) {
		boolean s = datasourceMap.containsKey(datasourceId);
		if (!s) {
			setting.putAll(datasourceId, config);
			datasourceIdList.add(datasourceId);
			datasourceMap.put(datasourceId, dsFactory.getDataSource(datasourceId));
			start(datasourceId);
		}
		return !s;
	}

	public DataSource getDataSource(String datasourceId) {
		String ref = refDatasourceIdMap.get(datasourceId);
		if (ObjectUtil.isEmpty(ref)) {
			return datasourceMap.get(datasourceId);
		} else {
			return datasourceMap.get(ref);
		}
		
	}

	public Map<String, String> getDataSourceConfig(String datasourceId) {
		String ref = refDatasourceIdMap.get(datasourceId);
		if (ObjectUtil.isEmpty(ref)) {
			return setting.getMap(datasourceId);
		} else {
			return setting.getMap(ref);
		}

	}

	public void start(String datasourceId) {
		try {
			String ref = refDatasourceIdMap.get(datasourceId);
			if (ObjectUtil.isNotEmpty(ref)) {
				return ;
			}
			Db db = getDb(datasourceId);
			DialectName dialectName = DialectName.valueOf(db.getRunner().getDialect().dialectName());
			String sql = "";
			switch (dialectName) {
			case MYSQL:
				sql = "select 1 from dual";
				break;
			case ORACLE:
				sql = "select * from dual";
				break;
			case SQLSERVER2012:
				sql = "select 1 as name";
				break;
			case SQLSERVER:
				sql = "select 1 as name";
				break;
			default:
				break;
			}
			if (ObjectUtil.isNotEmpty(sql)) {
				SQLExecutorDbMapper.getInstance(datasourceId, KVMap.class).count(sql);
			} else {
				throw new MFTException("不支持的数据库类型");
			}
		} catch (Exception e) {
			log.error("数据源[" + datasourceId + "]", e);
		}
	}

	public Db getDb(String datasourceId) {
		return Db.use(getDataSource(datasourceId));
	}

	public Session getSession(String datasourceId) {
		return Session.create(getDataSource(datasourceId));
	}

	public String dbType(String datasourceId) {
		Db db = getDb(datasourceId);
		DialectName dialectName = DialectName.valueOf(db.getRunner().getDialect().dialectName());
		return dialectName.name();
	}

	public String dbSchema(String datasourceId) {
		Db db = getDb(datasourceId);
		DialectName dialectName = DialectName.valueOf(db.getRunner().getDialect().dialectName());
		String dbSchema = datasourceId;
		switch (dialectName) {
		case MYSQL:
			String url = getDataSourceConfig(datasourceId).get("url");
			String[] arr = url.split("\\?");
			String string = arr[0];
			String[] array = string.split("/");
			dbSchema = array[array.length - 1];
			break;
		case ORACLE:
			dbSchema = getDataSourceConfig(datasourceId).get("username");
			break;
		default:
			break;
		}
		return dbSchema;
	}
}
